﻿//----------------------------------------------------------------
// Desc: lua 脚本中的函数对象
// Edit: ShowLong, http://blog.csdn.net/showlong
//
// Date Created: 2012-10-26
//
// Update Date : 
//
// Copyright (c) Fuel4D (http://www.fuel4d.com), All rights reserved.
//
//----------------------------------------------------------------
#pragma once


class IFLua;
class IFLuaFunc;
class IFLuaFuncParameter;


#define FLUA_TYPE(n) class   _Ty##n
#define FLUA_ARGC(n) _Ty##n   _v##n
#define FLUA_ARGR(n) _Ty##n & _v##n
#define FLUA_VAL(n)  _v##n

#define FLUA_TYPE1               FLUA_TYPE(1)
#define FLUA_TYPE2  FLUA_TYPE1,  FLUA_TYPE(2)
#define FLUA_TYPE3  FLUA_TYPE2,  FLUA_TYPE(3)
#define FLUA_TYPE4  FLUA_TYPE3,  FLUA_TYPE(4)
#define FLUA_TYPE5  FLUA_TYPE4,  FLUA_TYPE(5)
#define FLUA_TYPE6  FLUA_TYPE5,  FLUA_TYPE(6)
#define FLUA_TYPE7  FLUA_TYPE6,  FLUA_TYPE(7)
#define FLUA_TYPE8  FLUA_TYPE7,  FLUA_TYPE(8)
#define FLUA_TYPE9  FLUA_TYPE8,  FLUA_TYPE(9)
#define FLUA_TYPE10 FLUA_TYPE9,  FLUA_TYPE(10)
#define FLUA_TYPE11 FLUA_TYPE10, FLUA_TYPE(11)
#define FLUA_TYPE12 FLUA_TYPE11, FLUA_TYPE(12)

#define FLUA_ARGC1               FLUA_ARGC(1)
#define FLUA_ARGC2  FLUA_ARGC1,  FLUA_ARGC(2)
#define FLUA_ARGC3  FLUA_ARGC2,  FLUA_ARGC(3)
#define FLUA_ARGC4  FLUA_ARGC3,  FLUA_ARGC(4)
#define FLUA_ARGC5  FLUA_ARGC4,  FLUA_ARGC(5)
#define FLUA_ARGC6  FLUA_ARGC5,  FLUA_ARGC(6)
#define FLUA_ARGC7  FLUA_ARGC6,  FLUA_ARGC(7)
#define FLUA_ARGC8  FLUA_ARGC7,  FLUA_ARGC(8)
#define FLUA_ARGC9  FLUA_ARGC8,  FLUA_ARGC(9)
#define FLUA_ARGC10 FLUA_ARGC9,  FLUA_ARGC(10)
#define FLUA_ARGC11 FLUA_ARGC10, FLUA_ARGC(11)
#define FLUA_ARGC12 FLUA_ARGC11, FLUA_ARGC(12)

#define FLUA_ARGR1               FLUA_ARGR(1)
#define FLUA_ARGR2  FLUA_ARGR1,  FLUA_ARGR(2)
#define FLUA_ARGR3  FLUA_ARGR2,  FLUA_ARGR(3)
#define FLUA_ARGR4  FLUA_ARGR3,  FLUA_ARGR(4)
#define FLUA_ARGR5  FLUA_ARGR4,  FLUA_ARGR(5)
#define FLUA_ARGR6  FLUA_ARGR5,  FLUA_ARGR(6)
#define FLUA_ARGR7  FLUA_ARGR6,  FLUA_ARGR(7)
#define FLUA_ARGR8  FLUA_ARGR7,  FLUA_ARGR(8)
#define FLUA_ARGR9  FLUA_ARGR8,  FLUA_ARGR(9)
#define FLUA_ARGR10 FLUA_ARGR9,  FLUA_ARGR(10)
#define FLUA_ARGR11 FLUA_ARGR10, FLUA_ARGR(11)
#define FLUA_ARGR12 FLUA_ARGR11, FLUA_ARGR(12)

#define FLUA_VAL1              FLUA_VAL(1)
#define FLUA_VAL2  FLUA_VAL1,  FLUA_VAL(2)
#define FLUA_VAL3  FLUA_VAL2,  FLUA_VAL(3)
#define FLUA_VAL4  FLUA_VAL3,  FLUA_VAL(4)
#define FLUA_VAL5  FLUA_VAL4,  FLUA_VAL(5)
#define FLUA_VAL6  FLUA_VAL5,  FLUA_VAL(6)
#define FLUA_VAL7  FLUA_VAL6,  FLUA_VAL(7)
#define FLUA_VAL8  FLUA_VAL7,  FLUA_VAL(8)
#define FLUA_VAL9  FLUA_VAL8,  FLUA_VAL(9)
#define FLUA_VAL10 FLUA_VAL9,  FLUA_VAL(10)
#define FLUA_VAL11 FLUA_VAL10, FLUA_VAL(11)
#define FLUA_VAL12 FLUA_VAL11, FLUA_VAL(12)


class IFLuaFunc : public IFMemObject
{
protected:
    explicit IFLuaFunc()
    {}

public:
    enum TYPE_DEF
    {
        dt_nil,
        dt_bool, dt_char, dt_uchar, dt_short, dt_ushort, dt_int, dt_uint,
        dt_long, dt_ulong, dt_float, dt_double,
        dt_astr, dt_wstr,
    };
    union VALUE_DEF
    {
        bool b; char c;  unsigned char uc; short s; unsigned short us; int i; unsigned int ui;
        long l; unsigned long ul; float f; double df;
        const char* astr; const wchar_t* wstr;
    };
    struct DT
    {
        TYPE_DEF t;     // 类型
        VALUE_DEF v;    // 值
        // 构造
        FINLINE DT(TYPE_DEF c = dt_nil):t(c){}
        // bool
        FINLINE DT(bool c){ v.b = c; t = dt_bool; }
        FINLINE operator bool(){ FASSERT(t==dt_bool, _T("实际类型与期望的类型不匹配")); if (t==dt_bool) return v.b; return false; }
        // char
        FINLINE DT(char c){ v.c = c; t = dt_char; }
        FINLINE operator char(){ FASSERT(t==dt_char, _T("实际类型与期望的类型不匹配")); if (t==dt_char) return v.c; return 0; }
        // unsigned char
        FINLINE DT(unsigned char c){ v.uc = c; t = dt_uchar; }
        FINLINE operator unsigned char(){ FASSERT(t==dt_uchar, _T("实际类型与期望的类型不匹配")); if (t==dt_uchar) return v.uc; return 0; }
        // short
        FINLINE DT(short c){ v.s = c; t = dt_short; }
        FINLINE operator short(){ FASSERT(t==dt_short, _T("实际类型与期望的类型不匹配")); if (t==dt_short) return v.s; return 0; }
        // unsigned short
        FINLINE DT(unsigned short c){ v.us = c; t = dt_ushort; }
        FINLINE operator unsigned short(){ FASSERT(t==dt_ushort, _T("实际类型与期望的类型不匹配")); if (t==dt_ushort) return v.us; return 0; }
        // int
        FINLINE DT(int c){ v.i = c; t = dt_int; }
        FINLINE operator int(){ FASSERT(t==dt_int, _T("实际类型与期望的类型不匹配")); if (t==dt_int) return v.i; return 0; }
        // unsigned int
        FINLINE DT(unsigned int c){ v.ui = c; t = dt_uint; }
        FINLINE operator unsigned int(){ FASSERT(t==dt_uint, _T("实际类型与期望的类型不匹配")); if (t==dt_uint) return v.ui; return 0; }
        // long
        FINLINE DT(long c){ v.l = c; t = dt_long; }
        FINLINE operator long(){ FASSERT(t==dt_long, _T("实际类型与期望的类型不匹配")); if (t==dt_long) return v.l; return 0; }
        // unsigned long
        FINLINE DT(unsigned long c){ v.ul = c; t = dt_ulong; }
        FINLINE operator unsigned long(){ FASSERT(t==dt_ulong, _T("实际类型与期望的类型不匹配")); if (t==dt_ulong) return v.ul; return 0; }
        // float
        FINLINE DT(float c){ v.f = c; t = dt_float; }
        FINLINE operator float(){ FASSERT(t==dt_float, _T("实际类型与期望的类型不匹配")); if (t==dt_float) return v.f; return 0; }
        // unsigned float
        FINLINE DT(double c){ v.df = c; t = dt_double; }
        FINLINE operator double(){ FASSERT(t==dt_double, _T("实际类型与期望的类型不匹配")); if (t==dt_double) return v.df; return 0; }
        // const char*
        FINLINE DT(const char* c){ v.astr = c; t = dt_astr; }
        FINLINE operator const char*(){ FASSERT(t==dt_astr, _T("实际类型与期望的类型不匹配")); if (t==dt_astr) return v.astr; return _FNILA; }
        // const wchar_t*
        FINLINE DT(const wchar_t* c){ v.wstr = c; t = dt_wstr; }
        FINLINE operator const wchar_t*(){ FASSERT(t==dt_wstr, _T("实际类型与期望的类型不匹配")); if (t==dt_wstr) return v.wstr; return _FNILW; }
    };

    struct DT_RET
    {
        TYPE_DEF t;     // 类型
        void* v;        // 返回值保存地址
        // 构造
        FINLINE DT_RET(TYPE_DEF c = dt_nil):t(c){}
        // bool
        FINLINE DT_RET(bool& c){ v = (void*)&c; t = dt_bool; }
        // char
        FINLINE DT_RET(char& c){ v = (void*)&c; t = dt_char; }
        // unsigned char
        FINLINE DT_RET(unsigned char& c){ v = (void*)&c; t = dt_uchar; }
        // short
        FINLINE DT_RET(short& c){ v = (void*)&c; t = dt_short; }
        // unsigned short
        FINLINE DT_RET(unsigned short& c){ v = (void*)&c; t = dt_ushort; }
        // int
        FINLINE DT_RET(int& c){ v = (void*)&c; t = dt_int; }
        // unsigned int
        FINLINE DT_RET(unsigned int& c){ v = (void*)&c; t = dt_uint; }
        // long
        FINLINE DT_RET(long& c){ v = (void*)&c; t = dt_long; }
        // unsigned long
        FINLINE DT_RET(unsigned long& c){ v = (void*)&c; t = dt_ulong; }
        // float
        FINLINE DT_RET(float& c){ v = (void*)&c; t = dt_float; }
        // unsigned float
        FINLINE DT_RET(double& c){ v = (void*)&c; t = dt_double; }
        // const char*
        FINLINE DT_RET(const char*& c){ v = (void*)&c; t = dt_astr; }
        // const wchar_t*
        FINLINE DT_RET(const wchar_t*& c){ v = (void*)&c; t = dt_wstr; }
    };

    // 执行函数（一般不直接调用此函数，请使用 Run 函数）
    virtual bool __Execute(size_t rt_count, DT* pvdt, size_t count) = 0;
    // 获取执行结束后的返回值（一般不直接调用此函数，请使用 Ret 函数）
    virtual bool __GetResult(DT_RET* pvrt, size_t count) = 0;
    // 执行回调函数时的返回值设定
    virtual size_t __PushResult(DT* pvdt, size_t count) = 0;
    // 获取自己所属lua脚本对象
    virtual IFLua* GetLua() = 0;

    // 执行函数，可带参数或者不带参数
    // .rt_count 返回值数量
    //          （如果你对返回值不感兴趣就填0）
    //          （当你须要返回值且需要调用 Ret 函的话，那么此值必须要大于或等于你实际需要的返回值数量）
    // ._Ty[n] 参数类型及列表和自动数量
    // .return 返回执行是否成功（只有执行成功以后才能调用 Ret 函数）
    // 执行函数（无参）
    FINLINE bool Run(size_t rt_count = 0)
    { return __Execute(rt_count, 0, 0); }
    // 执行函数（多参）
#define FLUA_FUNC(n)\
    template < FLUA_TYPE##n >\
    FINLINE bool Run(size_t rt_count, FLUA_ARGC##n)\
    {\
        DT arg[n] = {FLUA_VAL##n};\
        return __Execute(rt_count, arg, n);\
    }
    FLUA_FUNC(1)    //  1个参数的 Run 函数
    FLUA_FUNC(2)    //  2个参数的 Run 函数
    FLUA_FUNC(3)    //  3个参数的 Run 函数
    FLUA_FUNC(4)    //  4个参数的 Run 函数
    FLUA_FUNC(5)    //  5个参数的 Run 函数
    FLUA_FUNC(6)    //  6个参数的 Run 函数
    FLUA_FUNC(7)    //  7个参数的 Run 函数
    FLUA_FUNC(8)    //  8个参数的 Run 函数
    FLUA_FUNC(9)    //  9个参数的 Run 函数
    FLUA_FUNC(10)   // 10个参数的 Run 函数
    FLUA_FUNC(11)   // 11个参数的 Run 函数
    FLUA_FUNC(12)   // 12个参数的 Run 函数

    // 获取函数返回值（注意返回的个数一定要小于等于执行Run函数时填的返回值个数）
#define FLUA_GET_RET(n)\
    template < FLUA_TYPE##n >\
    FINLINE bool GetRet(FLUA_ARGR##n)\
    {\
        DT_RET arg[n] = {FLUA_VAL##n};\
        return __GetResult(arg, n);\
    }
    FLUA_GET_RET(1)     //  1个参数的 GetRet 函数
    FLUA_GET_RET(2)     //  2个参数的 GetRet 函数
    FLUA_GET_RET(3)     //  3个参数的 GetRet 函数
    FLUA_GET_RET(4)     //  4个参数的 GetRet 函数
    FLUA_GET_RET(5)     //  5个参数的 GetRet 函数
    FLUA_GET_RET(6)     //  6个参数的 GetRet 函数
    FLUA_GET_RET(7)     //  7个参数的 GetRet 函数
    FLUA_GET_RET(8)     //  8个参数的 GetRet 函数
    FLUA_GET_RET(9)     //  9个参数的 GetRet 函数
    FLUA_GET_RET(10)    // 10个参数的 GetRet 函数
    FLUA_GET_RET(11)    // 11个参数的 GetRet 函数
    FLUA_GET_RET(12)    // 12个参数的 GetRet 函数
};


class IFLuaFuncParameter : public IFMemObject
{
protected:
    explicit IFLuaFuncParameter(IFLuaFunc* f)
        :func(f)
    {}

public:
    IFLuaFunc* func;    // 所属函数对象

    // 获取参数数量
    virtual size_t Count() = 0;
    // 获取指定位置的参数
    virtual bool GetIdx(IFLuaFunc::DT_RET rt, size_t idx) = 0;
    // 获取所有参数值
    virtual bool GetValue(IFLuaFunc::DT_RET* pvrt, size_t count) = 0;
    // 获取自己所属lua脚本对象
    FINLINE IFLua* GetLua(){ if (func) return func->GetLua(); return 0; }

    // 获取函数参数
#define FLUA_PARAM(n)\
    template < FLUA_TYPE##n >\
    FINLINE bool Get(FLUA_ARGR##n)\
    {\
        IFLuaFunc::DT_RET arg[n] = {FLUA_VAL##n};\
        return GetValue(arg, n);\
    }
    FLUA_PARAM(1)     //  1个参数
    FLUA_PARAM(2)     //  2个参数
    FLUA_PARAM(3)     //  3个参数
    FLUA_PARAM(4)     //  4个参数
    FLUA_PARAM(5)     //  5个参数
    FLUA_PARAM(6)     //  6个参数
    FLUA_PARAM(7)     //  7个参数
    FLUA_PARAM(8)     //  8个参数
    FLUA_PARAM(9)     //  9个参数
    FLUA_PARAM(10)    // 10个参数
    FLUA_PARAM(11)    // 11个参数
    FLUA_PARAM(12)    // 12个参数

    // 设置函数返回值（只在能回调函数中使用）
#define FLUA_PUSH_RET(n)\
    template < FLUA_TYPE##n >\
    FINLINE size_t PushRet(FLUA_ARGC##n)\
    {\
        IFLuaFunc::DT arg[n] = {FLUA_VAL##n};\
        return func->__PushResult(arg, n);\
    }
    FLUA_PUSH_RET(1)     //  1个返回值
    FLUA_PUSH_RET(2)     //  2个返回值
    FLUA_PUSH_RET(3)     //  3个返回值
    FLUA_PUSH_RET(4)     //  4个返回值
    FLUA_PUSH_RET(5)     //  5个返回值
    FLUA_PUSH_RET(6)     //  6个返回值
    FLUA_PUSH_RET(7)     //  7个返回值
    FLUA_PUSH_RET(8)     //  8个返回值
    FLUA_PUSH_RET(9)     //  9个返回值
    FLUA_PUSH_RET(10)    // 10个返回值
    FLUA_PUSH_RET(11)    // 11个返回值
    FLUA_PUSH_RET(12)    // 12个返回值
};


// 回调函数
// .args 参数列表
// .return 返回值个数
typedef size_t (*F_LUA_FUNC)(IFLuaFuncParameter* args);